其實最後這一系列 “聊聊美國找工作以及面試經驗”,本來預計寫個 3 - 4 個有趣題目、至少 3 篇面試準備/異國工作心得,殊不知光資料結構跟演算法就佔用了28 天了?。只能各挪一篇給他們。等之後 30 天結束再不定期寫一下面試前需要準備的事好了。
我過去是在專案公司上班,要馬使用者不多、要馬後台資料量不大,所以我在調效能方面總是很不上心 (完全不會為了快 0.01 秒多花好幾天時間去寫。專案公司根本也不會給你太多時間時做)。所以當第一次看到有 Debounce & Throttle 跟這種概念覺得非常聰明啊 !!! 聽說也是大公司面試很常考的題目之一
只要是使用者會在短時間內頻繁觸發多次事件處理器,例如 autocomplete、滑鼠移動、改變視窗大小都可以適用此篇。因為你的瀏覽器會不斷重新計算造成頁面很緩慢
在開始之前可以看一下這個網站感受不同方法的區別。
此篇就以 autocomplete 為例,什麼是 autocomplete 呢?
就是會有一個搜尋的 input
當你輸入文字時會自動出現相對應的結果。打 "H" 就會出現 "H" 開頭的結果提示你
打 "Ha" 同理會出現 "Ha" 開頭的結果
其實這功能很常實作到,也不困難。我都直接用 Array.prototype.filter 資料然後秀出來就完成!
但原來這只適用資料量不大的情況。因為使用者輸入一次你就要 filter 一次,假如使用者頻繁輸入就可能會影響到效能
2627. Debounce
設一個 timeout,例如輸入以後過兩秒才去抓一次使用者輸入值
function debounce(func, delay){
// timeout 初始值
let timeout = null;
return function(...args){
clearTimeout(timeout)
timeout = setTimeout(() => {
func(...args)
}, delay)
}
}
debounce(function(e){
console.log(e.target.value);
}, 2000)
原始碼
當你輸入 "H" 過 2 秒就會 print "H"(實務上就是過 2 秒才 autocomplete 去抓相關資料)。這應該沒甚麼問題
但當使用者一直頻繁輸入,
好處就是可以防止 js 頻繁去篩選資料,等待兩秒後再一次篩選就好
2676. Throttle
它防止一下輸入太頻繁的值,所以會限制一個時間,第一次結果會馬上顯示,然後會在 wait 時間內顯示最後一次存得值
function throttle(func, wait) {
let waiting = false, lastArgs = null;
// 紀錄最 wait 時間內最後的值
return (...args) => {
if(!waiting){
func(...args) // 第一次一定 trigger func
waiting = true;
let timeout = () => setTimeout(() => {
waiting = false; // 在還沒有到下一次 wait 都不會 trigger func
if(lastArgs){
func(...lastArgs);
waiting = true;
lastArgs = null;
timeout();
}
}, wait);
timeout();
}
else {
lastArgs = args //持續存值
}
}
}
throttle(function(e){
console.log(e.target.value);
}, 2000)
當你第 0 秒輸入 "H" 馬上會印 "H",接下來兩秒內程式都不會再印東西
直到第 2 秒才會印出來。所以以此類推在 第 0 秒、第 2 秒、第 4 秒時才會印出東西。
看到這邊應該可以感受到 Debounce 跟 Throttle 不同了。以輸入這個例子我是覺得會比較適合用 Debounce。但如果是偵測滑鼠移動 Throttle 就比較適合了。
這邊有我試做的 範例 可以上去玩玩看
如有錯誤或需要改進的地方,拜託跟我說。
我會以最快速度修改,感謝您
歡迎追蹤我的部落格,除了技術文也會分享一些在矽谷工作的甘苦。